Prepare data
Read and format data
Prevalence
df_uk_prev <- read_csv('UK_timeseries_prep_2005.csv')
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
date = [31mcol_character()[39m,
cumcase = [32mcol_double()[39m,
poptotal = [32mcol_double()[39m,
rate = [32mcol_double()[39m
)
df_uk_prev <- df_uk_prev %>%
select(ut_area, date, rate) %>%
rename(rate_day = rate) %>%
mutate(date = as.Date(date, "%d%b%Y"))
df_uk_prev
Personality
df_uk_pers <- read_csv('timeseries_uk_utla_march9_april_09.csv')
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
time = [32mcol_double()[39m,
areaname = [31mcol_character()[39m,
open = [32mcol_double()[39m,
extra = [32mcol_double()[39m,
agree = [32mcol_double()[39m,
neuro = [32mcol_double()[39m,
sci = [32mcol_double()[39m,
frequ = [32mcol_double()[39m,
ut_name = [31mcol_character()[39m,
poptotal = [32mcol_double()[39m,
rate_day = [32mcol_double()[39m
)
df_uk_pers <- df_uk_pers %>%
select(ut_area, open, agree, neuro, sci, extra) %>%
dplyr::rename(pers_o = open,
pers_c = sci,
pers_e = extra,
pers_a = agree,
pers_n = neuro) %>%
distinct()
df_uk_pers
NA
Social distancing
df_uk_socdist <- read_csv('UK_socdist_fb_nuts3.csv')
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
date = [34mcol_date(format = "")[39m,
all_day_bing_tiles_visited_relat = [32mcol_double()[39m,
all_day_ratio_single_tile_users = [32mcol_double()[39m,
open = [32mcol_double()[39m,
extra = [32mcol_double()[39m,
agree = [32mcol_double()[39m,
neuro = [32mcol_double()[39m,
sci = [32mcol_double()[39m,
frequ = [32mcol_double()[39m,
nuts3_name = [31mcol_character()[39m,
runday = [32mcol_double()[39m
)
df_uk_socdist$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-03-01" "2020-03-08" "2020-03-16" "2020-03-16" "2020-03-24" "2020-03-31"
df_uk_socdist <- df_uk_socdist %>% select(-runday, -frequ) %>%
dplyr::rename(pers_o = open,
pers_c = sci,
pers_e = extra,
pers_a = agree,
pers_n = neuro) %>%
select(-nuts3_name) %>%
dplyr::rename(socdist_tiles = all_day_bing_tiles_visited_relat,
socdist_single_tile = all_day_ratio_single_tile_users) %>%
drop_na()
df_uk_socdist
Controls
df_uk_ctrl_nuts <- read_csv("controls_UK_nuts3.csv")
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
nuts3_name = [31mcol_character()[39m,
airport_dist = [32mcol_double()[39m,
males = [32mcol_double()[39m,
popdens = [32mcol_double()[39m,
manufacturing = [32mcol_double()[39m,
tourism = [32mcol_double()[39m,
health = [32mcol_double()[39m,
academic = [32mcol_double()[39m,
medinc = [32mcol_double()[39m,
medage = [32mcol_double()[39m,
conservative = [32mcol_double()[39m
)
df_uk_ctrl_nuts <- df_uk_ctrl_nuts %>% select(-nuts3_name)
df_uk_ctrl_nuts
df_uk_ctrl_ut <- read_csv("controls_UK_ut.csv")
Parsed with column specification:
cols(
ut_area = [31mcol_character()[39m,
ut_name = [31mcol_character()[39m,
airport_dist = [32mcol_double()[39m,
males = [32mcol_double()[39m,
popdens = [32mcol_double()[39m,
manufacturing = [32mcol_double()[39m,
tourism = [32mcol_double()[39m,
health = [32mcol_double()[39m,
academic = [32mcol_double()[39m,
medinc = [32mcol_double()[39m,
medage = [32mcol_double()[39m,
conservative = [32mcol_double()[39m
)
df_uk_ctrl_ut <- df_uk_ctrl_ut %>% select(-ut_name)
df_uk_ctrl_ut
NA
NA
Merge prevalence data
df_uk_prev <- df_uk_prev %>%
plyr::join(df_uk_pers, by='ut_area') %>%
plyr::join(df_uk_ctrl_ut, by='ut_area')
# create sequence of dates
date_sequence <- seq.Date(min(df_uk_prev$date),
max(df_uk_prev$date), 1)
# create data frame with time sequence
df_dates = tibble(date_sequence, 1:length(date_sequence))
names(df_dates) <- c('date', 'time')
# merge day index with gps data
df_uk_prev = df_uk_prev %>%
merge(df_dates, by='date') %>%
arrange(ut_area) %>%
as_tibble()
df_uk_prev
Merge social distancing data
nuts_ut_key <- read_csv('nuts3_ut.csv')
Parsed with column specification:
cols(
nuts3 = [31mcol_character()[39m,
ut_area = [31mcol_character()[39m
)
df_uk_socdist <- df_uk_socdist %>% plyr::join(df_uk_ctrl_nuts, by='nuts3')
df_uk_socdist <- nuts_ut_key %>%
inner_join(df_uk_socdist, by = c('nuts3')) %>%
inner_join(select(df_uk_prev, ut_area, date, rate_day), by = c('ut_area', 'date')) %>%
select(-ut_area)
# create sequence of dates
date_sequence <- seq.Date(min(df_uk_socdist$date),
max(df_uk_socdist$date), 1)
# create data frame with time sequence
df_dates = tibble(date_sequence, 1:length(date_sequence))
names(df_dates) <- c('date', 'time')
# merge day index with gps data
df_uk_socdist = df_uk_socdist %>%
merge(df_dates, by='date') %>%
arrange(nuts3) %>%
as_tibble()
df_uk_socdist
NA
Identify London areas
nuts_london_inner <- c('UKI31','UKI32','UKI33','UKI34','UKI41',
'UKI42','UKI43','UKI44','UKI45')
nuts_london_outer <- c('UKI51','UKI52','UKI53','UKI54','UKI61',
'UKI62','UKI63','UKI71','UKI72','UKI73',
'UKI74','UKI75')
ut_london_inner <- c('E09000007','E09000001','E09000033','E09000013',
'E09000020','E09000032','E09000025','E09000012',
'E09000030','E09000014','E09000019','E09000023',
'E09000028','E09000022')
ut_london_outer <- c('E09000011','E09000004','E09000016','E09000002',
'E09000031','E09000026','E09000010','E09000006',
'E09000008','E09000029','E09000021','E09000024',
'E09000003','E09000005','E09000009','E09000017',
'E09000015','E09000018','E09000027')
df_uk_prev = df_uk_prev %>%
mutate(london = ifelse(ut_area %in% ut_london_inner, 'london_inner',
ifelse(ut_area %in% ut_london_outer, 'london_outer',
'country'))) %>%
mutate(london = as.factor(london))
df_uk_socdist = df_uk_socdist %>%
mutate(london = ifelse(nuts3 %in% nuts_london_inner, 'london_inner',
ifelse(nuts3 %in% nuts_london_outer, 'london_outer',
'country'))) %>%
mutate(london = as.factor(london))
Check timeframes
df_uk_prev$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-01-30" "2020-02-26" "2020-03-24" "2020-03-24" "2020-04-21" "2020-05-18"
df_uk_socdist$date %>% summary()
Min. 1st Qu. Median Mean 3rd Qu. Max.
"2020-03-01" "2020-03-08" "2020-03-16" "2020-03-16" "2020-03-24" "2020-03-31"
Control for weekend effect in social distancing
df_uk_loess <- df_uk_socdist %>%
mutate(weekday = format(date, '%u')) %>%
filter(!weekday %in% c('6','7')) %>%
split(.$nuts3) %>%
map(~ loess(socdist_single_tile ~ time, data = .)) %>%
map(predict, 1:max(df_uk_socdist$time)) %>%
bind_rows() %>%
gather(key = 'nuts3', value = 'loess') %>%
group_by(nuts3) %>%
mutate(time = row_number())
df_uk_loess
df_uk_socdist <- df_uk_socdist %>% merge(df_uk_loess, by=c('nuts3', 'time')) %>%
mutate(weekday = format(date, '%u')) %>%
mutate(socdist_single_tile_clean = ifelse(weekday %in% c('6','7'), loess,
socdist_single_tile)) %>%
arrange(nuts3, time) %>%
select(-weekday)
df_uk_socdist <- df_uk_socdist %>% drop_na() %>% mutate(time = time-1)
Explore data
Plot prevalence over time
df_uk_prev %>% ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
ggtitle("Overall prevalence over time")

pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')
for (i in pers){
gg <- df_uk_prev %>% mutate(prev_tail = cut(.[[i]],
breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
labels = c('lower tail', 'center', 'upper tail'))) %>%
filter(prev_tail != 'center') %>%
ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
facet_wrap(~prev_tail) +
theme(legend.position="none") +
ggtitle(i)
print(gg)
}





Explore differences between london and the rest
df_uk_prev %>% ggplot(aes(x=time, y=rate_day)) +
geom_point(aes(col=ut_area, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
facet_wrap(~london) +
ggtitle("Overall prevalence over time")

NA
NA
NA
Plot social distancing over time
df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
ggtitle("Overall social distancing over time")

pers <- c('pers_o', 'pers_c', 'pers_e', 'pers_a', 'pers_n')
for (i in pers){
gg <- df_uk_socdist %>% mutate(socdist_tail = cut(.[[i]],
breaks = c(-Inf, quantile(.[[i]], 0.2), quantile(.[[i]], 0.8), Inf),
labels = c('lower tail', 'center', 'upper tail'))) %>%
filter(socdist_tail != 'center') %>%
ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
facet_wrap(~socdist_tail) +
theme(legend.position="none") +
ggtitle(i)
print(gg)
}





df_uk_socdist %>% ggplot(aes(x=time, y=socdist_single_tile_clean)) +
geom_point(aes(col=nuts3, size=popdens)) +
geom_smooth(method="loess", se=T) +
theme(legend.position="none") +
facet_wrap(~london) +
ggtitle("Overall social distancing over time")

df_uk_socdist <- df_uk_socdist %>% mutate(socdist_single_tile = socdist_single_tile_clean) %>%
select(-loess, -socdist_single_tile_clean)
Correlations
df_uk_prev %>% group_by(ut_area) %>%
summarize_if(is.numeric, mean, na.rm=T) %>%
select(-ut_area, -time) %>%
cor(use = 'pairwise.complete') %>% round(3) %>%
as.data.frame()
df_uk_socdist %>% group_by(nuts3) %>%
summarize_if(is.numeric, mean, na.rm=T) %>%
select(-nuts3, -time) %>%
cor(use = 'pairwise.complete') %>% round(3) %>%
as.data.frame()
NA
Rescale Data
lvl2_scaled_ut <- df_uk_prev %>%
dplyr::select(-time, -date, -rate_day, -london) %>%
distinct() %>%
mutate_at(vars(-ut_area), scale)
lvl1_scaled_ut <- df_uk_prev %>% select(ut_area, time, rate_day)
df_uk_prev_scaled <- plyr::join(lvl1_scaled_ut, lvl2_scaled_ut, by = 'ut_area')
df_uk_prev_scaled
lvl2_scaled_nuts <- df_uk_socdist %>%
dplyr::select(-time, -date, -london,
-socdist_tiles, -socdist_single_tile, -rate_day) %>%
distinct() %>%
mutate_at(vars(-nuts3), scale)
lvl1_scaled_nuts <- df_uk_socdist %>% select(nuts3, time, socdist_single_tile, rate_day) %>%
mutate_at(vars(-nuts3, -time, - rate_day), scale)
df_uk_socdist_scaled <- plyr::join(lvl1_scaled_nuts, lvl2_scaled_nuts, by = 'nuts3')
df_uk_socdist_scaled
NA
Predict Prevalence
Explore distributions
df_uk_onset_prev %>% ggplot(aes(onset_prev)) + geom_histogram()

df_uk_slope_prev %>% ggplot(aes(slope_prev)) + geom_histogram()

Predict COVID onset with time-to-event regression
# predict onset from personality
cox_onset_prev <- coxph(Surv(onset_prev, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_onset_prev)
cox_onset_prev %>% summary()
Call:
coxph(formula = Surv(onset_prev, event) ~ pers_o + pers_c + pers_e +
pers_a + pers_n, data = df_uk_onset_prev)
n= 149, number of events= 149
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.322264 1.380249 0.166864 1.931 0.0534 .
pers_c 0.036475 1.037149 0.135119 0.270 0.7872
pers_e -0.013895 0.986201 0.143396 -0.097 0.9228
pers_a 0.005323 1.005338 0.106927 0.050 0.9603
pers_n -0.092400 0.911740 0.106197 -0.870 0.3843
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.3802 0.7245 0.9952 1.914
pers_c 1.0371 0.9642 0.7958 1.352
pers_e 0.9862 1.0140 0.7446 1.306
pers_a 1.0053 0.9947 0.8153 1.240
pers_n 0.9117 1.0968 0.7404 1.123
Concordance= 0.605 (se = 0.027 )
Likelihood ratio test= 12.64 on 5 df, p=0.03
Wald test = 13.47 on 5 df, p=0.02
Score (logrank) test = 13.78 on 5 df, p=0.02
# predict onset from personality with controls
cox_onset_prev_ctrl <- coxph(Surv(onset_prev, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_onset_prev)
cox_onset_prev_ctrl %>% summary()
Call:
coxph(formula = Surv(onset_prev, event) ~ pers_o + pers_c + pers_e +
pers_a + pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_onset_prev)
n= 144, number of events= 144
(5 observations deleted due to missingness)
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.13431 1.14375 0.26537 0.506 0.6128
pers_c 0.27571 1.31746 0.21410 1.288 0.1978
pers_e -0.28546 0.75167 0.16166 -1.766 0.0774 .
pers_a 0.15618 1.16904 0.12936 1.207 0.2273
pers_n -0.04289 0.95801 0.13821 -0.310 0.7563
airport_dist 0.08819 1.09219 0.10241 0.861 0.3892
males -0.28751 0.75013 0.11525 -2.495 0.0126 *
popdens 0.31764 1.37388 0.22294 1.425 0.1542
manufacturing -0.01434 0.98576 0.15053 -0.095 0.9241
tourism 0.20101 1.22263 0.12897 1.559 0.1191
health -0.13046 0.87769 0.09930 -1.314 0.1889
academic 0.41323 1.51170 0.25879 1.597 0.1103
medinc -0.10312 0.90201 0.15281 -0.675 0.4998
medage -0.54104 0.58214 0.21413 -2.527 0.0115 *
conservative -0.05175 0.94957 0.28447 -0.182 0.8557
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.1438 0.8743 0.6799 1.9241
pers_c 1.3175 0.7590 0.8660 2.0044
pers_e 0.7517 1.3304 0.5475 1.0319
pers_a 1.1690 0.8554 0.9072 1.5064
pers_n 0.9580 1.0438 0.7307 1.2561
airport_dist 1.0922 0.9156 0.8936 1.3350
males 0.7501 1.3331 0.5985 0.9402
popdens 1.3739 0.7279 0.8875 2.1267
manufacturing 0.9858 1.0144 0.7339 1.3240
tourism 1.2226 0.8179 0.9496 1.5742
health 0.8777 1.1394 0.7225 1.0663
academic 1.5117 0.6615 0.9103 2.5104
medinc 0.9020 1.1086 0.6686 1.2170
medage 0.5821 1.7178 0.3826 0.8857
conservative 0.9496 1.0531 0.5437 1.6583
Concordance= 0.643 (se = 0.027 )
Likelihood ratio test= 37.26 on 15 df, p=0.001
Wald test = 39.13 on 15 df, p=6e-04
Score (logrank) test = 40.98 on 15 df, p=3e-04
Predict prevalence slopes with linear models
# predict slopes from personality
lm_slope_prev <- lm(slope_prev ~ pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_slope_prev)
lm_slope_prev %>% summary()
Call:
lm(formula = slope_prev ~ pers_o + pers_c + pers_e + pers_a +
pers_n, data = df_uk_slope_prev)
Residuals:
Min 1Q Median 3Q Max
-1.7860 -0.6362 -0.2094 0.7033 2.6714
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.002131 0.079563 0.027 0.97867
pers_o -0.333971 0.156768 -2.130 0.03492 *
pers_c -0.410825 0.131422 -3.126 0.00216 **
pers_e 0.185648 0.146531 1.267 0.20731
pers_a -0.079900 0.113176 -0.706 0.48139
pers_n -0.010203 0.117778 -0.087 0.93109
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9544 on 138 degrees of freedom
Multiple R-squared: 0.121, Adjusted R-squared: 0.0892
F-statistic: 3.801 on 5 and 138 DF, p-value: 0.002952
lm_slope_prev %>% confint(level=0.9)
5 % 95 %
(Intercept) -0.12962227 0.13388435
pers_o -0.59357311 -0.07436818
pers_c -0.62845610 -0.19319326
pers_e -0.05700314 0.42829908
pers_a -0.26731588 0.10751684
pers_n -0.20523983 0.18483327
# predict slopes from personality with controls
lm_slope_prev_ctrl <- lm(slope_prev ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_slope_prev)
lm_slope_prev_ctrl %>% summary()
Call:
lm(formula = slope_prev ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_slope_prev)
Residuals:
Min 1Q Median 3Q Max
-1.5547 -0.6035 -0.1290 0.5089 2.5138
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.0001885 0.0762728 0.002 0.9980
pers_o -0.2077366 0.2283946 -0.910 0.3648
pers_c -0.4171252 0.1786161 -2.335 0.0211 *
pers_e 0.0766020 0.1510128 0.507 0.6128
pers_a 0.0244037 0.1325550 0.184 0.8542
pers_n -0.0565544 0.1348334 -0.419 0.6756
airport_dist -0.2553608 0.1004444 -2.542 0.0122 *
males -0.0929729 0.1132149 -0.821 0.4131
popdens 0.3584047 0.1939178 1.848 0.0669 .
manufacturing 0.0044476 0.1308607 0.034 0.9729
tourism -0.0448877 0.1109015 -0.405 0.6863
health 0.1020422 0.0961094 1.062 0.2904
academic -0.0444398 0.2325892 -0.191 0.8488
medinc 0.2191543 0.1408175 1.556 0.1221
medage 0.2639820 0.1864681 1.416 0.1593
conservative 0.3114007 0.2528659 1.231 0.2204
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9135 on 128 degrees of freedom
Multiple R-squared: 0.253, Adjusted R-squared: 0.1655
F-statistic: 2.89 on 15 and 128 DF, p-value: 0.0006055
lm_slope_prev_ctrl %>% confint(level=0.9)
5 % 95 %
(Intercept) -0.12618377 0.12656074
pers_o -0.58615113 0.17067793
pers_c -0.71306452 -0.12118593
pers_e -0.17360284 0.32680684
pers_a -0.19521936 0.24402685
pers_n -0.27995244 0.16684370
airport_dist -0.42178168 -0.08893997
males -0.28055246 0.09460666
popdens 0.03711285 0.67969647
manufacturing -0.21236829 0.22126358
tourism -0.22863438 0.13885896
health -0.05719619 0.26128051
academic -0.42980408 0.34092454
medinc -0.01415856 0.45246713
medage -0.04496690 0.57293081
conservative -0.10755887 0.73036030
CRF predicting slopes
ctrls <- cforest_unbiased(ntree=500, mtry=5)
crf_slope_prev <- cforest(slope_prev ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_slope_prev,
controls = ctrls)
crf_slope_prev_varimp <- varimp(crf_slope_prev, nperm = 1)
crf_slope_prev_varimp_cond <- varimp(crf_slope_prev, conditional = T, nperm = 1)
crf_slope_prev_varimp
pers_o pers_c pers_e pers_a pers_n airport_dist
-0.001157014 0.053747726 0.001291754 0.020462011 0.005438448 0.108365253
males popdens manufacturing tourism health academic
0.007400495 0.092050722 0.003048002 0.010678059 0.004215513 0.016715474
medinc medage conservative
0.023809632 0.008239030 0.001390651
crf_slope_prev_varimp %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

crf_slope_prev_varimp_cond
pers_o pers_c pers_e pers_a pers_n airport_dist
0.0006295733 0.0561321826 0.0022530095 0.0196145597 0.0080475020 0.1003499343
males popdens manufacturing tourism health academic
0.0086626130 0.0903354666 0.0095705435 0.0125389217 0.0036556077 0.0123883068
medinc medage conservative
0.0237284345 0.0147654779 0.0047480179
crf_slope_prev_varimp_cond %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

Predict Social Distancing
Change point analysis
# keep only counties with full data
nuts_complete <- df_uk_socdist_scaled %>%
group_by(nuts3) %>%
summarize(n = n()) %>%
filter(n==max(.$n)) %>%
.$nuts3
# run changepoint analysis
df_uk_socdist_cpt_results <- df_uk_socdist_scaled %>%
select(nuts3, socdist_single_tile) %>%
filter(nuts3 %in% nuts_complete) %>%
split(.$nuts3) %>%
map(~ cpt.meanvar(as.vector(.$socdist_single_tile),
#penalty = 'Asymptotic',
class=TRUE,
param.estimates=TRUE,
Q=1,
test.stat = 'Normal'))
# calculate change point
df_uk_socdist_cpt_day <- df_uk_socdist_cpt_results %>%
map(cpts) %>%
unlist() %>%
as.data.frame() %>%
rename(cpt_day_socdist = '.') %>%
rownames_to_column('nuts3')
# calculate mean differences
df_uk_socdist_cpt_mean_diff <- df_uk_socdist_cpt_results %>%
map(param.est) %>%
map(~ .$mean) %>%
map(~ .[2]-.[1]) %>%
unlist() %>%
as.data.frame() %>%
rename(mean_diff_socdist = '.') %>%
rownames_to_column('nuts3')
# calculate varaince differences
df_uk_socdist_cpt_var_diff <- df_uk_socdist_cpt_results %>%
map(param.est) %>%
map(~ .$variance) %>%
map(~ .[2]-.[1]) %>%
unlist() %>%
as.data.frame() %>%
rename(var_diff_socdist = '.') %>%
rownames_to_column('nuts3')
# merge with county data
df_uk_cpt_socdist <- df_uk_socdist_scaled %>%
select(-time, -rate_day, -socdist_single_tile) %>%
distinct() %>%
left_join(df_uk_socdist_cpt_day, by='nuts3') %>%
left_join(df_uk_socdist_cpt_mean_diff, by='nuts3') %>%
left_join(df_uk_socdist_cpt_var_diff, by='nuts3') %>%
left_join(nuts_ut_key, by='nuts3') %>%
left_join(select(df_uk_onset_prev, ut_area, onset_prev), by='ut_area') %>%
left_join(select(df_uk_slope_prev, ut_area, slope_prev), by='ut_area') %>%
select(-ut_area)
# standardize mean/var differences
df_uk_cpt_socdist <- df_uk_cpt_socdist %>%
mutate(mean_diff_socdist = scale(mean_diff_socdist),
var_diff_socdist = scale(var_diff_socdist))
# handle censored data
df_uk_cpt_socdist <- df_uk_cpt_socdist %>%
mutate(cpt_day_socdist = ifelse(is.na(cpt_day_socdist),
as.numeric(diff(range(df_us$date))),
cpt_day_socdist)) %>%
mutate(event = ifelse(cpt_day_socdist >= 60, 0, 1))
df_uk_cpt_socdist$cpt_day_socdist %>% hist()

df_uk_cpt_socdist$mean_diff_socdist %>% hist()

df_uk_cpt_socdist$var_diff_socdist %>% hist()

for(i in head(df_uk_socdist_cpt_results, 5)){
plot(i)
}




NA

Predicting change points with time-to-event regression
# predict hazard from personality
cox_cpt_socdist <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_cpt_socdist)
cox_cpt_socdist %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n, data = df_uk_cpt_socdist)
n= 131, number of events= 131
coef exp(coef) se(coef) z Pr(>|z|)
pers_o 0.02292 1.02319 0.14906 0.154 0.878
pers_c 0.01178 1.01185 0.14322 0.082 0.934
pers_e 0.17493 1.19117 0.14723 1.188 0.235
pers_a -0.19324 0.82428 0.11907 -1.623 0.105
pers_n -0.01502 0.98509 0.12389 -0.121 0.903
exp(coef) exp(-coef) lower .95 upper .95
pers_o 1.0232 0.9773 0.7640 1.370
pers_c 1.0118 0.9883 0.7642 1.340
pers_e 1.1912 0.8395 0.8926 1.590
pers_a 0.8243 1.2132 0.6527 1.041
pers_n 0.9851 1.0151 0.7727 1.256
Concordance= 0.672 (se = 0.046 )
Likelihood ratio test= 11.4 on 5 df, p=0.04
Wald test = 13.38 on 5 df, p=0.02
Score (logrank) test = 13.55 on 5 df, p=0.02
# predict hazard from personality with controls
cox_cpt_socdist_ctrl <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_cpt_socdist)
cox_cpt_socdist_ctrl %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n + airport_dist + males + popdens +
manufacturing + tourism + health + academic + medinc + medage +
conservative, data = df_uk_cpt_socdist)
n= 131, number of events= 131
coef exp(coef) se(coef) z Pr(>|z|)
pers_o -0.100979 0.903952 0.243690 -0.414 0.6786
pers_c -0.048635 0.952528 0.198550 -0.245 0.8065
pers_e 0.080996 1.084366 0.163732 0.495 0.6208
pers_a -0.006914 0.993110 0.162410 -0.043 0.9660
pers_n 0.204498 1.226909 0.151016 1.354 0.1757
airport_dist 0.251102 1.285441 0.126736 1.981 0.0476 *
males -0.148267 0.862201 0.142494 -1.041 0.2981
popdens 0.158406 1.171641 0.233680 0.678 0.4979
manufacturing -0.083042 0.920313 0.130937 -0.634 0.5259
tourism -0.254837 0.775043 0.142800 -1.785 0.0743 .
health -0.266804 0.765823 0.122195 -2.183 0.0290 *
academic 0.153738 1.166185 0.247465 0.621 0.5344
medinc 0.166816 1.181537 0.177460 0.940 0.3472
medage -0.008602 0.991435 0.216020 -0.040 0.9682
conservative -0.180652 0.834726 0.268518 -0.673 0.5011
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 0.9040 1.1063 0.5607 1.4574
pers_c 0.9525 1.0498 0.6455 1.4057
pers_e 1.0844 0.9222 0.7867 1.4947
pers_a 0.9931 1.0069 0.7224 1.3653
pers_n 1.2269 0.8151 0.9126 1.6495
airport_dist 1.2854 0.7779 1.0027 1.6479
males 0.8622 1.1598 0.6521 1.1400
popdens 1.1716 0.8535 0.7411 1.8523
manufacturing 0.9203 1.0866 0.7120 1.1896
tourism 0.7750 1.2903 0.5858 1.0254
health 0.7658 1.3058 0.6027 0.9731
academic 1.1662 0.8575 0.7180 1.8941
medinc 1.1815 0.8464 0.8344 1.6730
medage 0.9914 1.0086 0.6492 1.5141
conservative 0.8347 1.1980 0.4932 1.4129
Concordance= 0.756 (se = 0.043 )
Likelihood ratio test= 30.64 on 15 df, p=0.01
Wald test = 31.24 on 15 df, p=0.008
Score (logrank) test = 32.93 on 15 df, p=0.005
# predict hazard from personality with controls
cox_cpt_socdist_ctrl2 <- coxph(Surv(cpt_day_socdist, event) ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist)
cox_cpt_socdist_ctrl2 %>% summary()
Call:
coxph(formula = Surv(cpt_day_socdist, event) ~ pers_o + pers_c +
pers_e + pers_a + pers_n + airport_dist + males + popdens +
manufacturing + tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev, data = df_uk_cpt_socdist)
n= 130, number of events= 130
(1 observation deleted due to missingness)
coef exp(coef) se(coef) z Pr(>|z|)
pers_o -0.100212 0.904646 0.249257 -0.402 0.6877
pers_c -0.116321 0.890189 0.207001 -0.562 0.5742
pers_e 0.081829 1.085271 0.163065 0.502 0.6158
pers_a 0.052790 1.054208 0.173127 0.305 0.7604
pers_n 0.231265 1.260194 0.157150 1.472 0.1411
airport_dist 0.216381 1.241576 0.129069 1.676 0.0936 .
males -0.216077 0.805673 0.156020 -1.385 0.1661
popdens 0.318647 1.375265 0.254074 1.254 0.2098
manufacturing -0.068862 0.933456 0.131435 -0.524 0.6003
tourism -0.253111 0.776382 0.144734 -1.749 0.0803 .
health -0.274628 0.759854 0.126715 -2.167 0.0302 *
academic 0.074328 1.077160 0.255443 0.291 0.7711
medinc 0.275566 1.317276 0.187601 1.469 0.1419
medage 0.044065 1.045050 0.217531 0.203 0.8395
conservative -0.168110 0.845261 0.269262 -0.624 0.5324
onset_prev -0.001956 0.998046 0.014702 -0.133 0.8941
slope_prev -0.190561 0.826495 0.166046 -1.148 0.2511
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
exp(coef) exp(-coef) lower .95 upper .95
pers_o 0.9046 1.1054 0.5550 1.4745
pers_c 0.8902 1.1234 0.5933 1.3356
pers_e 1.0853 0.9214 0.7884 1.4940
pers_a 1.0542 0.9486 0.7509 1.4801
pers_n 1.2602 0.7935 0.9261 1.7148
airport_dist 1.2416 0.8054 0.9641 1.5990
males 0.8057 1.2412 0.5934 1.0939
popdens 1.3753 0.7271 0.8358 2.2628
manufacturing 0.9335 1.0713 0.7215 1.2077
tourism 0.7764 1.2880 0.5846 1.0310
health 0.7599 1.3160 0.5927 0.9741
academic 1.0772 0.9284 0.6529 1.7771
medinc 1.3173 0.7591 0.9120 1.9027
medage 1.0450 0.9569 0.6823 1.6007
conservative 0.8453 1.1831 0.4986 1.4328
onset_prev 0.9980 1.0020 0.9697 1.0272
slope_prev 0.8265 1.2099 0.5969 1.1444
Concordance= 0.745 (se = 0.044 )
Likelihood ratio test= 32.6 on 17 df, p=0.01
Wald test = 32.53 on 17 df, p=0.01
Score (logrank) test = 33.98 on 17 df, p=0.008
Linear models predicting mean differences
lm_meandiff_socdist <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n,
data = df_uk_cpt_socdist)
lm_meandiff_socdist %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n, data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-1.64579 -0.51491 -0.01039 0.44273 2.01175
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -6.652e-16 6.716e-02 0.000 1.000000
pers_o -3.237e-02 1.226e-01 -0.264 0.792145
pers_c -2.732e-01 1.121e-01 -2.437 0.016220 *
pers_e 4.179e-01 1.186e-01 3.523 0.000596 ***
pers_a -1.442e-01 9.870e-02 -1.461 0.146648
pers_n -2.791e-02 9.783e-02 -0.285 0.775854
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.7687 on 125 degrees of freedom
Multiple R-squared: 0.4319, Adjusted R-squared: 0.4092
F-statistic: 19.01 on 5 and 125 DF, p-value: 5.03e-14
lm_meandiff_socdist %>% confint(level=0.9)
5 % 95 %
(Intercept) -0.1112898 0.11128979
pers_o -0.2354792 0.17074155
pers_c -0.4590535 -0.08743620
pers_e 0.2213206 0.61442966
pers_a -0.3077064 0.01940226
pers_n -0.1900323 0.13420232
lm_meandiff_socdist_ctrl <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative,
data = df_uk_cpt_socdist)
lm_meandiff_socdist_ctrl %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative,
data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-1.67572 -0.44003 -0.00968 0.35644 1.43938
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.736e-15 5.265e-02 0.000 1.0000
pers_o -2.278e-01 1.536e-01 -1.483 0.1407
pers_c -9.103e-02 1.238e-01 -0.735 0.4638
pers_e 8.363e-02 1.022e-01 0.819 0.4148
pers_a 2.510e-01 9.761e-02 2.571 0.0114 *
pers_n 1.598e-01 8.524e-02 1.875 0.0633 .
airport_dist -1.452e-01 7.427e-02 -1.955 0.0530 .
males -1.790e-01 8.763e-02 -2.043 0.0434 *
popdens 6.472e-01 1.373e-01 4.713 6.9e-06 ***
manufacturing -1.761e-01 8.167e-02 -2.156 0.0332 *
tourism -7.244e-02 7.820e-02 -0.926 0.3562
health -3.648e-03 6.918e-02 -0.053 0.9580
academic 1.971e-01 1.538e-01 1.282 0.2025
medinc 1.833e-01 1.014e-01 1.809 0.0731 .
medage -9.010e-03 1.351e-01 -0.067 0.9469
conservative -3.433e-02 1.725e-01 -0.199 0.8427
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.6026 on 115 degrees of freedom
Multiple R-squared: 0.6787, Adjusted R-squared: 0.6368
F-statistic: 16.2 on 15 and 115 DF, p-value: < 2.2e-16
lm_meandiff_socdist_ctrl %>% confint(level=0.9)
5 % 95 %
(Intercept) -0.08730925 0.08730925
pers_o -0.48240052 0.02684553
pers_c -0.29639278 0.11433553
pers_e -0.08579590 0.25305877
pers_a 0.08909523 0.41281599
pers_n 0.01848059 0.30116470
airport_dist -0.26833237 -0.02203087
males -0.32433391 -0.03370903
popdens 0.41946976 0.87487594
manufacturing -0.31150145 -0.04065515
tourism -0.20212145 0.05723813
health -0.11836208 0.11106574
academic -0.05790764 0.45210902
medinc 0.01525667 0.35142884
medage -0.23303105 0.21501107
conservative -0.32043114 0.25177936
lm_meandiff_socdist_ctrl2 <- lm(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist)
lm_meandiff_socdist_ctrl2 %>% summary()
Call:
lm(formula = mean_diff_socdist ~ pers_o + pers_c + pers_e + pers_a +
pers_n + airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage + conservative +
onset_prev + slope_prev, data = df_uk_cpt_socdist)
Residuals:
Min 1Q Median 3Q Max
-1.73062 -0.41506 0.00236 0.39176 1.51083
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.298362 0.279045 1.069 0.2873
pers_o -0.246641 0.155683 -1.584 0.1160
pers_c -0.063355 0.124995 -0.507 0.6133
pers_e 0.087719 0.102359 0.857 0.3933
pers_a 0.248985 0.097577 2.552 0.0121 *
pers_n 0.152392 0.085413 1.784 0.0771 .
airport_dist -0.124048 0.075185 -1.650 0.1018
males -0.125131 0.093003 -1.345 0.1812
popdens 0.599144 0.143775 4.167 6.09e-05 ***
manufacturing -0.182290 0.082628 -2.206 0.0294 *
tourism -0.077232 0.078515 -0.984 0.3274
health -0.006028 0.069266 -0.087 0.9308
academic 0.197328 0.154892 1.274 0.2053
medinc 0.149825 0.103537 1.447 0.1507
medage -0.003030 0.135821 -0.022 0.9822
conservative -0.054715 0.172815 -0.317 0.7521
onset_prev -0.008423 0.008221 -1.025 0.3078
slope_prev 0.158185 0.088247 1.793 0.0757 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.602 on 112 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.6857, Adjusted R-squared: 0.638
F-statistic: 14.38 on 17 and 112 DF, p-value: < 2.2e-16
lm_meandiff_socdist_ctrl2 %>% confint(level=0.9)
5 % 95 %
(Intercept) -0.16445432 0.7611787168
pers_o -0.50485339 0.0115709223
pers_c -0.27066775 0.1439583777
pers_e -0.08205015 0.2574879916
pers_a 0.08714679 0.4108234557
pers_n 0.01072830 0.2940549875
airport_dist -0.24874786 0.0006528252
males -0.27938403 0.0291211026
popdens 0.36068190 0.8376060752
manufacturing -0.31933404 -0.0452456984
tourism -0.20745495 0.0529914399
health -0.12090990 0.1088538858
academic -0.05957178 0.4542275782
medinc -0.02189838 0.3215476531
medage -0.22829969 0.2222397258
conservative -0.34134071 0.2319101786
onset_prev -0.02205782 0.0052120593
slope_prev 0.01182114 0.3045482089
CRF predicting mean difference
ctrls <- cforest_unbiased(ntree=500, mtry=5)
crf_meandiff_socdist <- cforest(mean_diff_socdist ~
pers_o + pers_c + pers_e + pers_a + pers_n +
airport_dist + males + popdens + manufacturing +
tourism + health + academic + medinc + medage +
conservative + onset_prev + slope_prev,
data = df_uk_cpt_socdist %>% drop_na(),
controls = ctrls)
crf_meandiff_socdist_varimp <- varimp(crf_meandiff_socdist, nperm = 1)
crf_meandiff_socdist_varimp_cond <- varimp(crf_meandiff_socdist, conditional = T, nperm = 1)
crf_meandiff_socdist_varimp
pers_o pers_c pers_e pers_a pers_n airport_dist
0.0232844793 0.0122480819 0.0403477261 0.0059899957 -0.0005080761 0.0450846205
males popdens manufacturing tourism health academic
0.0008135687 0.2838876443 0.0443088789 0.0069334919 0.0020621555 0.1013815679
medinc medage conservative onset_prev slope_prev
0.0923793299 0.0412885652 0.1093241022 0.0007741436 0.0078232998
crf_meandiff_socdist_varimp %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

crf_meandiff_socdist_varimp_cond
pers_o pers_c pers_e pers_a pers_n airport_dist
2.220321e-02 1.266544e-02 3.619921e-02 2.757494e-03 -1.068532e-04 5.066091e-02
males popdens manufacturing tourism health academic
5.051975e-04 2.708944e-01 3.938252e-02 6.477050e-03 2.565017e-03 9.055470e-02
medinc medage conservative onset_prev slope_prev
9.946050e-02 4.130137e-02 1.009788e-01 -3.928147e-05 1.067222e-02
crf_meandiff_socdist_varimp_cond %>% as.data.frame() %>%
rownames_to_column('variable') %>%
ggplot(aes(x=variable, y=.)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(angle = 90))

Export data
uk_list_results <- list(cox_onset_prev, cox_onset_prev_ctrl,
lm_slope_prev, lm_slope_prev_ctrl,
cox_cpt_socdist, cox_cpt_socdist_ctrl, cox_cpt_socdist_ctrl2,
lm_meandiff_socdist, lm_meandiff_socdist_ctrl, lm_meandiff_socdist_ctrl2)
results_names <- list('cox_onset_prev', 'cox_onset_prev_ctrl',
'lm_slope_prev', 'lm_slope_prev_coef',
'cox_cpt_socdist', 'cox_cpt_socdist_ctrl', 'cox_cpt_socdist_ctrl2',
'lm_meandiff_socdist', 'lm_meandiff_socdist_ctrl', 'lm_meandiff_socdist_ctrl2')
names(uk_list_results) <- results_names
save(uk_list_results, file="uk_list_results.RData")
write_csv(df_uk_slope_prev, 'df_uk_slope_prev.csv')
write_csv(df_uk_cpt_socdist, 'df_uk_cpt_socdist.csv')
LS0tCnRpdGxlOiAiQ09WSUQxOSBVSyIKYXV0aG9yOiAiSGVpbnJpY2ggUGV0ZXJzIgpkYXRlOiAiNC8yMy8yMDIwIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKCiMgTUFDCiBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICcvVXNlcnMvaHAyNTAwL0dvb2dsZSBEcml2ZS9TVFVEWS9Db2x1bWJpYS9SZXNlYXJjaC9Db3JvbmEvRGF0YS9VSycpCiAKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhcnR5KQpsaWJyYXJ5KGRvUGFyYWxsZWwpCmxpYnJhcnkoY2hhbmdlcG9pbnQpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkoc3Vydm1pbmVyKQoKYGBgCgojIFByZXBhcmUgZGF0YQoKIyMjIFJlYWQgYW5kIGZvcm1hdCBkYXRhCgojIyMgUHJldmFsZW5jZSAKCmBgYHtyfQpkZl91a19wcmV2IDwtIHJlYWRfY3N2KCdVS190aW1lc2VyaWVzX3ByZXBfMjAwNS5jc3YnKQoKZGZfdWtfcHJldiA8LSBkZl91a19wcmV2ICU+JSAKICBzZWxlY3QodXRfYXJlYSwgZGF0ZSwgcmF0ZSkgJT4lIAogIHJlbmFtZShyYXRlX2RheSA9IHJhdGUpICU+JQogIG11dGF0ZShkYXRlID0gYXMuRGF0ZShkYXRlLCAiJWQlYiVZIikpCgpkZl91a19wcmV2CmBgYAoKIyMjIFBlcnNvbmFsaXR5CmBgYHtyfQoKZGZfdWtfcGVycyA8LSByZWFkX2NzdigndGltZXNlcmllc191a191dGxhX21hcmNoOV9hcHJpbF8wOS5jc3YnKQoKZGZfdWtfcGVycyA8LSBkZl91a19wZXJzICU+JSAKICBzZWxlY3QodXRfYXJlYSwgb3BlbiwgYWdyZWUsIG5ldXJvLCBzY2ksIGV4dHJhKSAlPiUgCiAgZHBseXI6OnJlbmFtZShwZXJzX28gPSBvcGVuLCAKICAgICAgICAgcGVyc19jID0gc2NpLAogICAgICAgICBwZXJzX2UgPSBleHRyYSwKICAgICAgICAgcGVyc19hID0gYWdyZWUsCiAgICAgICAgIHBlcnNfbiA9IG5ldXJvKSAlPiUKICBkaXN0aW5jdCgpCgpkZl91a19wZXJzCgpgYGAKCiMjIyBTb2NpYWwgZGlzdGFuY2luZwpgYGB7cn0KZGZfdWtfc29jZGlzdCA8LSByZWFkX2NzdignVUtfc29jZGlzdF9mYl9udXRzMy5jc3YnKQpkZl91a19zb2NkaXN0JGRhdGUgJT4lIHN1bW1hcnkoKQoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBzZWxlY3QoLXJ1bmRheSwgLWZyZXF1KSAlPiUKICBkcGx5cjo6cmVuYW1lKHBlcnNfbyA9IG9wZW4sIAogICAgICAgICAgICAgICAgcGVyc19jID0gc2NpLAogICAgICAgICAgICAgICAgcGVyc19lID0gZXh0cmEsCiAgICAgICAgICAgICAgICBwZXJzX2EgPSBhZ3JlZSwKICAgICAgICAgICAgICAgIHBlcnNfbiA9IG5ldXJvKSAlPiUgCiAgc2VsZWN0KC1udXRzM19uYW1lKSAlPiUgCiAgZHBseXI6OnJlbmFtZShzb2NkaXN0X3RpbGVzID0gYWxsX2RheV9iaW5nX3RpbGVzX3Zpc2l0ZWRfcmVsYXQsCiAgICAgICAgICAgICAgICBzb2NkaXN0X3NpbmdsZV90aWxlID0gYWxsX2RheV9yYXRpb19zaW5nbGVfdGlsZV91c2VycykgJT4lCiAgZHJvcF9uYSgpCgpkZl91a19zb2NkaXN0CmBgYAoKIyMjIENvbnRyb2xzIApgYGB7cn0KZGZfdWtfY3RybF9udXRzIDwtIHJlYWRfY3N2KCJjb250cm9sc19VS19udXRzMy5jc3YiKQpkZl91a19jdHJsX251dHMgPC0gZGZfdWtfY3RybF9udXRzICU+JSBzZWxlY3QoLW51dHMzX25hbWUpCmRmX3VrX2N0cmxfbnV0cwoKCmRmX3VrX2N0cmxfdXQgPC0gcmVhZF9jc3YoImNvbnRyb2xzX1VLX3V0LmNzdiIpCmRmX3VrX2N0cmxfdXQgPC0gZGZfdWtfY3RybF91dCAlPiUgc2VsZWN0KC11dF9uYW1lKQpkZl91a19jdHJsX3V0CgoKYGBgCgoKCgoKIyMjIE1lcmdlIHByZXZhbGVuY2UgZGF0YSAKYGBge3J9CmRmX3VrX3ByZXYgPC0gZGZfdWtfcHJldiAlPiUgCiAgcGx5cjo6am9pbihkZl91a19wZXJzLCBieT0ndXRfYXJlYScpICU+JSAKICBwbHlyOjpqb2luKGRmX3VrX2N0cmxfdXQsIGJ5PSd1dF9hcmVhJykKCiMgY3JlYXRlIHNlcXVlbmNlIG9mIGRhdGVzCmRhdGVfc2VxdWVuY2UgPC0gc2VxLkRhdGUobWluKGRmX3VrX3ByZXYkZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX3VrX3ByZXYkZGF0ZSksIDEpCiAgICAgICAgICAgICAgICAgICAgIAojIGNyZWF0ZSBkYXRhIGZyYW1lIHdpdGggdGltZSBzZXF1ZW5jZQpkZl9kYXRlcyA9IHRpYmJsZShkYXRlX3NlcXVlbmNlLCAxOmxlbmd0aChkYXRlX3NlcXVlbmNlKSkgCm5hbWVzKGRmX2RhdGVzKSA8LSBjKCdkYXRlJywgJ3RpbWUnKQoKIyBtZXJnZSBkYXkgaW5kZXggd2l0aCBncHMgZGF0YQpkZl91a19wcmV2ID0gZGZfdWtfcHJldiAlPiUgCiAgbWVyZ2UoZGZfZGF0ZXMsIGJ5PSdkYXRlJykgJT4lIAogIGFycmFuZ2UodXRfYXJlYSkgJT4lCiAgYXNfdGliYmxlKCkKCmRmX3VrX3ByZXYKYGBgCgojIyMgTWVyZ2Ugc29jaWFsIGRpc3RhbmNpbmcgZGF0YQpgYGB7cn0KCm51dHNfdXRfa2V5IDwtIHJlYWRfY3N2KCdudXRzM191dC5jc3YnKQpkZl91a19zb2NkaXN0IDwtIGRmX3VrX3NvY2Rpc3QgJT4lIHBseXI6OmpvaW4oZGZfdWtfY3RybF9udXRzLCBieT0nbnV0czMnKQoKZGZfdWtfc29jZGlzdCA8LSBudXRzX3V0X2tleSAlPiUgCiAgaW5uZXJfam9pbihkZl91a19zb2NkaXN0LCBieSA9IGMoJ251dHMzJykpICU+JQogIGlubmVyX2pvaW4oc2VsZWN0KGRmX3VrX3ByZXYsIHV0X2FyZWEsIGRhdGUsIHJhdGVfZGF5KSwgYnkgPSBjKCd1dF9hcmVhJywgJ2RhdGUnKSkgJT4lCiAgc2VsZWN0KC11dF9hcmVhKQoKIyBjcmVhdGUgc2VxdWVuY2Ugb2YgZGF0ZXMKZGF0ZV9zZXF1ZW5jZSA8LSBzZXEuRGF0ZShtaW4oZGZfdWtfc29jZGlzdCRkYXRlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoZGZfdWtfc29jZGlzdCRkYXRlKSwgMSkKICAgICAgICAgICAgICAgICAgICAgCiMgY3JlYXRlIGRhdGEgZnJhbWUgd2l0aCB0aW1lIHNlcXVlbmNlCmRmX2RhdGVzID0gdGliYmxlKGRhdGVfc2VxdWVuY2UsIDE6bGVuZ3RoKGRhdGVfc2VxdWVuY2UpKSAKbmFtZXMoZGZfZGF0ZXMpIDwtIGMoJ2RhdGUnLCAndGltZScpCgojIG1lcmdlIGRheSBpbmRleCB3aXRoIGdwcyBkYXRhCmRmX3VrX3NvY2Rpc3QgPSBkZl91a19zb2NkaXN0ICU+JSAKICBtZXJnZShkZl9kYXRlcywgYnk9J2RhdGUnKSAlPiUgCiAgYXJyYW5nZShudXRzMykgJT4lCiAgYXNfdGliYmxlKCkKCgpkZl91a19zb2NkaXN0CgpgYGAKCiMjIyBJZGVudGlmeSBMb25kb24gYXJlYXMKYGBge3J9CgpudXRzX2xvbmRvbl9pbm5lciA8LSBjKCdVS0kzMScsJ1VLSTMyJywnVUtJMzMnLCdVS0kzNCcsJ1VLSTQxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k0MicsJ1VLSTQzJywnVUtJNDQnLCdVS0k0NScpCgpudXRzX2xvbmRvbl9vdXRlciA8LSBjKCdVS0k1MScsJ1VLSTUyJywnVUtJNTMnLCdVS0k1NCcsJ1VLSTYxJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k2MicsJ1VLSTYzJywnVUtJNzEnLCdVS0k3MicsJ1VLSTczJywKICAgICAgICAgICAgICAgICAgICAgICdVS0k3NCcsJ1VLSTc1JykKCnV0X2xvbmRvbl9pbm5lciA8LSBjKCdFMDkwMDAwMDcnLCdFMDkwMDAwMDEnLCdFMDkwMDAwMzMnLCdFMDkwMDAwMTMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjAnLCdFMDkwMDAwMzInLCdFMDkwMDAwMjUnLCdFMDkwMDAwMTInLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMzAnLCdFMDkwMDAwMTQnLCdFMDkwMDAwMTknLCdFMDkwMDAwMjMnLAogICAgICAgICAgICAgICAgICAgICdFMDkwMDAwMjgnLCdFMDkwMDAwMjInKQoKdXRfbG9uZG9uX291dGVyIDwtIGMoJ0UwOTAwMDAxMScsJ0UwOTAwMDAwNCcsJ0UwOTAwMDAxNicsJ0UwOTAwMDAwMicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAzMScsJ0UwOTAwMDAyNicsJ0UwOTAwMDAxMCcsJ0UwOTAwMDAwNicsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwOCcsJ0UwOTAwMDAyOScsJ0UwOTAwMDAyMScsJ0UwOTAwMDAyNCcsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAwMycsJ0UwOTAwMDAwNScsJ0UwOTAwMDAwOScsJ0UwOTAwMDAxNycsCiAgICAgICAgICAgICAgICAgICAgJ0UwOTAwMDAxNScsJ0UwOTAwMDAxOCcsJ0UwOTAwMDAyNycpCmBgYAoKYGBge3J9CgpkZl91a19wcmV2ID0gZGZfdWtfcHJldiAlPiUgCiAgbXV0YXRlKGxvbmRvbiA9IGlmZWxzZSh1dF9hcmVhICVpbiUgdXRfbG9uZG9uX2lubmVyLCAnbG9uZG9uX2lubmVyJywgCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHV0X2FyZWEgJWluJSB1dF9sb25kb25fb3V0ZXIsICdsb25kb25fb3V0ZXInLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY291bnRyeScpKSkgJT4lCiAgbXV0YXRlKGxvbmRvbiA9IGFzLmZhY3Rvcihsb25kb24pKQoKZGZfdWtfc29jZGlzdCA9IGRmX3VrX3NvY2Rpc3QgJT4lIAogIG11dGF0ZShsb25kb24gPSBpZmVsc2UobnV0czMgJWluJSBudXRzX2xvbmRvbl9pbm5lciwgJ2xvbmRvbl9pbm5lcicsIAogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShudXRzMyAlaW4lIG51dHNfbG9uZG9uX291dGVyLCAnbG9uZG9uX291dGVyJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvdW50cnknKSkpICU+JQogIG11dGF0ZShsb25kb24gPSBhcy5mYWN0b3IobG9uZG9uKSkKCmBgYAoKIyMjIENoZWNrIHRpbWVmcmFtZXMgCmBgYHtyfQpkZl91a19wcmV2JGRhdGUgJT4lIHN1bW1hcnkoKQpkZl91a19zb2NkaXN0JGRhdGUgJT4lIHN1bW1hcnkoKQpgYGAKCiMjIyBDb250cm9sIGZvciB3ZWVrZW5kIGVmZmVjdCBpbiBzb2NpYWwgZGlzdGFuY2luZwpgYGB7cn0KCmRmX3VrX2xvZXNzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIAogIG11dGF0ZSh3ZWVrZGF5ID0gZm9ybWF0KGRhdGUsICcldScpKSAlPiUgCiAgZmlsdGVyKCF3ZWVrZGF5ICVpbiUgYygnNicsJzcnKSkgJT4lIAogIHNwbGl0KC4kbnV0czMpICU+JQogIG1hcCh+IGxvZXNzKHNvY2Rpc3Rfc2luZ2xlX3RpbGUgfiB0aW1lLCBkYXRhID0gLikpICU+JQogIG1hcChwcmVkaWN0LCAxOm1heChkZl91a19zb2NkaXN0JHRpbWUpKSAlPiUgCiAgYmluZF9yb3dzKCkgJT4lIAogIGdhdGhlcihrZXkgPSAnbnV0czMnLCB2YWx1ZSA9ICdsb2VzcycpICU+JSAKICBncm91cF9ieShudXRzMykgJT4lIAogIG11dGF0ZSh0aW1lID0gcm93X251bWJlcigpKQoKZGZfdWtfbG9lc3MKCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgbWVyZ2UoZGZfdWtfbG9lc3MsIGJ5PWMoJ251dHMzJywgJ3RpbWUnKSkgJT4lIAogIG11dGF0ZSh3ZWVrZGF5ID0gZm9ybWF0KGRhdGUsICcldScpKSAlPiUgCiAgbXV0YXRlKHNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4gPSBpZmVsc2Uod2Vla2RheSAlaW4lIGMoJzYnLCc3JyksIGxvZXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvY2Rpc3Rfc2luZ2xlX3RpbGUpKSAlPiUKICBhcnJhbmdlKG51dHMzLCB0aW1lKSAlPiUgCiAgc2VsZWN0KC13ZWVrZGF5KQoKCmRmX3VrX3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdCAlPiUgZHJvcF9uYSgpICU+JSBtdXRhdGUodGltZSA9IHRpbWUtMSkKCmBgYAoKIyBFeHBsb3JlIGRhdGEKCiMjIyBQbG90IHByZXZhbGVuY2Ugb3ZlciB0aW1lCmBgYHtyfQoKZGZfdWtfcHJldiAlPiUgZ2dwbG90KGFlcyh4PXRpbWUsIHk9cmF0ZV9kYXkpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD11dF9hcmVhLCBzaXplPXBvcGRlbnMpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBzZT1UKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKCJPdmVyYWxsIHByZXZhbGVuY2Ugb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19wcmV2ICU+JSBtdXRhdGUocHJldl90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIocHJldl90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1yYXRlX2RheSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sPXV0X2FyZWEsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+cHJldl90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgojIyMgRXhwbG9yZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGxvbmRvbiBhbmQgdGhlIHJlc3QgCmBgYHtyfQoKZGZfdWtfcHJldiAlPiUgZ2dwbG90KGFlcyh4PXRpbWUsIHk9cmF0ZV9kYXkpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD11dF9hcmVhLCBzaXplPXBvcGRlbnMpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBzZT1UKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBmYWNldF93cmFwKH5sb25kb24pICsKICBnZ3RpdGxlKCJPdmVyYWxsIHByZXZhbGVuY2Ugb3ZlciB0aW1lIikKCgoKYGBgCgojIyMgUGxvdCBzb2NpYWwgZGlzdGFuY2luZyBvdmVyIHRpbWUKYGBge3J9CgpkZl91a19zb2NkaXN0ICU+JSBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGdndGl0bGUoIk92ZXJhbGwgc29jaWFsIGRpc3RhbmNpbmcgb3ZlciB0aW1lIikKCnBlcnMgPC0gYygncGVyc19vJywgJ3BlcnNfYycsICdwZXJzX2UnLCAncGVyc19hJywgJ3BlcnNfbicpCgpmb3IgKGkgaW4gcGVycyl7CgpnZyA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF90YWlsID0gY3V0KC5bW2ldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgcXVhbnRpbGUoLltbaV1dLCAwLjIpLCBxdWFudGlsZSguW1tpXV0sIDAuOCksIEluZiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoJ2xvd2VyIHRhaWwnLCAnY2VudGVyJywgJ3VwcGVyIHRhaWwnKSkpICU+JSAKICBmaWx0ZXIoc29jZGlzdF90YWlsICE9ICdjZW50ZXInKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dGltZSwgeT1zb2NkaXN0X3NpbmdsZV90aWxlX2NsZWFuKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2w9bnV0czMsIHNpemU9cG9wZGVucykpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsb2VzcyIsIHNlPVQpICsgCiAgZmFjZXRfd3JhcCh+c29jZGlzdF90YWlsKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBnZ3RpdGxlKGkpCgpwcmludChnZykKfQoKYGBgCgoKYGBge3J9CmRmX3VrX3NvY2Rpc3QgJT4lIGdncGxvdChhZXMoeD10aW1lLCB5PXNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4pKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbD1udXRzMywgc2l6ZT1wb3BkZW5zKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgc2U9VCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgZmFjZXRfd3JhcCh+bG9uZG9uKSArCiAgZ2d0aXRsZSgiT3ZlcmFsbCBzb2NpYWwgZGlzdGFuY2luZyBvdmVyIHRpbWUiKQpgYGAKCmBgYHtyfQoKZGZfdWtfc29jZGlzdCA8LSBkZl91a19zb2NkaXN0ICU+JSBtdXRhdGUoc29jZGlzdF9zaW5nbGVfdGlsZSA9IHNvY2Rpc3Rfc2luZ2xlX3RpbGVfY2xlYW4pICU+JSAKICBzZWxlY3QoLWxvZXNzLCAtc29jZGlzdF9zaW5nbGVfdGlsZV9jbGVhbikKCmBgYAoKIyMjIENvcnJlbGF0aW9ucwpgYGB7cn0KCmRmX3VrX3ByZXYgJT4lIGdyb3VwX2J5KHV0X2FyZWEpICU+JSAKICBzdW1tYXJpemVfaWYoaXMubnVtZXJpYywgbWVhbiwgbmEucm09VCkgJT4lIAogIHNlbGVjdCgtdXRfYXJlYSwgLXRpbWUpICU+JSAKICBjb3IodXNlID0gJ3BhaXJ3aXNlLmNvbXBsZXRlJykgJT4lIHJvdW5kKDMpICU+JQogIGFzLmRhdGEuZnJhbWUoKQoKZGZfdWtfc29jZGlzdCAlPiUgZ3JvdXBfYnkobnV0czMpICU+JSAKICBzdW1tYXJpemVfaWYoaXMubnVtZXJpYywgbWVhbiwgbmEucm09VCkgJT4lIAogIHNlbGVjdCgtbnV0czMsIC10aW1lKSAlPiUgCiAgY29yKHVzZSA9ICdwYWlyd2lzZS5jb21wbGV0ZScpICU+JSByb3VuZCgzKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpCgpgYGAKCgojIyBSZXNjYWxlIERhdGEKYGBge3J9Cmx2bDJfc2NhbGVkX3V0IDwtIGRmX3VrX3ByZXYgJT4lIAogIGRwbHlyOjpzZWxlY3QoLXRpbWUsIC1kYXRlLCAtcmF0ZV9kYXksIC1sb25kb24pICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBtdXRhdGVfYXQodmFycygtdXRfYXJlYSksIHNjYWxlKQoKbHZsMV9zY2FsZWRfdXQgPC0gZGZfdWtfcHJldiAlPiUgc2VsZWN0KHV0X2FyZWEsIHRpbWUsIHJhdGVfZGF5KQoKZGZfdWtfcHJldl9zY2FsZWQgPC0gcGx5cjo6am9pbihsdmwxX3NjYWxlZF91dCwgbHZsMl9zY2FsZWRfdXQsIGJ5ID0gJ3V0X2FyZWEnKQoKZGZfdWtfcHJldl9zY2FsZWQKYGBgCgoKYGBge3J9CgpsdmwyX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIAogIGRwbHlyOjpzZWxlY3QoLXRpbWUsIC1kYXRlLCAtbG9uZG9uLCAKICAgICAgICAgICAgICAgIC1zb2NkaXN0X3RpbGVzLCAtc29jZGlzdF9zaW5nbGVfdGlsZSwgLXJhdGVfZGF5KSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoLW51dHMzKSwgc2NhbGUpCgpsdmwxX3NjYWxlZF9udXRzIDwtIGRmX3VrX3NvY2Rpc3QgJT4lIHNlbGVjdChudXRzMywgdGltZSwgc29jZGlzdF9zaW5nbGVfdGlsZSwgcmF0ZV9kYXkpICU+JSAKICBtdXRhdGVfYXQodmFycygtbnV0czMsIC10aW1lLCAtIHJhdGVfZGF5KSwgc2NhbGUpCgpkZl91a19zb2NkaXN0X3NjYWxlZCA8LSBwbHlyOjpqb2luKGx2bDFfc2NhbGVkX251dHMsIGx2bDJfc2NhbGVkX251dHMsIGJ5ID0gJ251dHMzJykKCmRmX3VrX3NvY2Rpc3Rfc2NhbGVkCgpgYGAKCgoKCiMgUHJlZGljdCBQcmV2YWxlbmNlCiMjIyBFeHRyYWN0IGZpcnN0IGRheSBvZiBjb3ZpZCBvdXRicmVhawpgYGB7cn0KCiMgZ2V0IG9uc2V0IGRheQpkZl91a19vbnNldF9wcmV2IDwtIGRmX3VrX3ByZXZfc2NhbGVkICU+JSAKICBncm91cF9ieSh1dF9hcmVhKSAlPiUgCiAgbXV0YXRlKHJhdGVfY3MgPSBjdW1zdW0ocmF0ZV9kYXkpKSAlPiUgCiAgZmlsdGVyKHJhdGVfY3MgPiAwKSAlPiUKICBzdW1tYXJpemUob25zZXRfcHJldiA9IG1pbih0aW1lKSkKICAKIyBtZXJnZSB3aXRoIGNvdW50eSBkYXRhCmRmX3VrX29uc2V0X3ByZXYgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIAogIHNlbGVjdCgtdGltZSwgLXJhdGVfZGF5KSAlPiUKICBkaXN0aW5jdCgpICU+JSAKICBsZWZ0X2pvaW4oZGZfdWtfb25zZXRfcHJldiwgYnkgPSAndXRfYXJlYScpCgojIGhhbmRsZSBjZW5zb3JlZCBkYXRhCmRmX3VrX29uc2V0X3ByZXYgPC0gZGZfdWtfb25zZXRfcHJldiAlPiUgCiAgbXV0YXRlKGV2ZW50ID0gaWZlbHNlKGlzLm5hKG9uc2V0X3ByZXYpLCAwLCAxKSkgJT4lIAogIG11dGF0ZShvbnNldF9wcmV2ID0gcmVwbGFjZV9uYShvbnNldF9wcmV2LCBhcy5udW1lcmljKGRpZmYocmFuZ2UoZGZfdWtfcHJldiRkYXRlKSkpKzEpKQoKYGBgCgojIyMgRXh0cmFjdCBzbG9wZXMKYGBge3J9CgojIGN1dCB0aW1lIHNlcmllcyBiZWZvcmUgb25zZXQKZGZfdWtfcHJldl9zY2FsZWQgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIAogIGdyb3VwX2J5KHV0X2FyZWEpICU+JSAKICBtdXRhdGUocmF0ZV9jcyA9IGN1bXN1bShyYXRlX2RheSkpICU+JSAKICBmaWx0ZXIocmF0ZV9jcyA+IDApICU+JQogIG11dGF0ZSh0aW1lID0gdGltZS1taW4odGltZSkrMSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcih0aW1lIDw9IDMwKSAlPiUKICBzZWxlY3QoLXJhdGVfY3MpCgojIGRyb3AgY291bnRpZXMgd2l0aCBsaXR0bGUgZGF0YQpkZl91a19wcmV2X3NjYWxlZCA8LSBkZl91a19wcmV2X3NjYWxlZCAlPiUKICBncm91cF9ieSh1dF9hcmVhKSAlPiUKICBmaWx0ZXIobigpID09IDMwKSAlPiUKICB1bmdyb3VwKCkKCiMgZXh0cmFjdCBzbG9wZSBwcmV2YWxlbmNlCmRmX3VrX3Nsb3BlX3ByZXYgPC0gZGZfdWtfcHJldl9zY2FsZWQgJT4lIHNwbGl0KC4kdXRfYXJlYSkgJT4lIAogIG1hcCh+IGxtKHJhdGVfZGF5IH4gdGltZSwgZGF0YSA9IC4pKSAlPiUKICBtYXAoY29lZikgJT4lIAogIG1hcF9kYmwoJ3RpbWUnKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3V0X2FyZWEnKSAlPiUgCiAgcmVuYW1lKHNsb3BlX3ByZXYgPSAnLicpCgojIG1lcmdlIHdpdGggY291bnR5IGRhdGEKZGZfdWtfc2xvcGVfcHJldiA8LSBkZl91a19wcmV2X3NjYWxlZCAlPiUgCiAgc2VsZWN0KC10aW1lLCAtcmF0ZV9kYXkpICU+JQogIGRpc3RpbmN0KCkgJT4lIAogIGlubmVyX2pvaW4oZGZfdWtfc2xvcGVfcHJldiwgYnkgPSAndXRfYXJlYScpICU+JQogIGRyb3BfbmEoKQoKIyBzdGFuZGFyZGl6ZSBzbG9wZXMKZGZfdWtfc2xvcGVfcHJldiA8LSBkZl91a19zbG9wZV9wcmV2ICU+JSAKICBtdXRhdGUoc2xvcGVfcHJldiA9IHNjYWxlKHNsb3BlX3ByZXYpKQpgYGAKCgojIyMgRXhwbG9yZSBkaXN0cmlidXRpb25zCmBgYHtyfQoKZGZfdWtfb25zZXRfcHJldiAlPiUgZ2dwbG90KGFlcyhvbnNldF9wcmV2KSkgKyBnZW9tX2hpc3RvZ3JhbSgpCmRmX3VrX3Nsb3BlX3ByZXYgJT4lIGdncGxvdChhZXMoc2xvcGVfcHJldikpICsgZ2VvbV9oaXN0b2dyYW0oKQoKYGBgCgoKIyMgUHJlZGljdCBDT1ZJRCBvbnNldCB3aXRoIHRpbWUtdG8tZXZlbnQgcmVncmVzc2lvbiAKYGBge3J9CgojIHByZWRpY3Qgb25zZXQgZnJvbSBwZXJzb25hbGl0eQpjb3hfb25zZXRfcHJldiA8LSBjb3hwaChTdXJ2KG9uc2V0X3ByZXYsIGV2ZW50KSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19vbnNldF9wcmV2KQpjb3hfb25zZXRfcHJldiAlPiUgc3VtbWFyeSgpCgojIHByZWRpY3Qgb25zZXQgZnJvbSBwZXJzb25hbGl0eSB3aXRoIGNvbnRyb2xzCmNveF9vbnNldF9wcmV2X2N0cmwgPC0gY294cGgoU3VydihvbnNldF9wcmV2LCBldmVudCkgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArIHBvcGRlbnMgKyBtYW51ZmFjdHVyaW5nICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3VyaXNtICsgaGVhbHRoICsgYWNhZGVtaWMgKyBtZWRpbmMgKyBtZWRhZ2UgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc2VydmF0aXZlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19vbnNldF9wcmV2KQpjb3hfb25zZXRfcHJldl9jdHJsICU+JSBzdW1tYXJ5KCkKCmBgYAoKCiMjIFByZWRpY3QgcHJldmFsZW5jZSBzbG9wZXMgd2l0aCBsaW5lYXIgbW9kZWxzCmBgYHtyfQoKIyBwcmVkaWN0IHNsb3BlcyBmcm9tIHBlcnNvbmFsaXR5CmxtX3Nsb3BlX3ByZXYgPC0gbG0oc2xvcGVfcHJldiB+IHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2xvcGVfcHJldikKbG1fc2xvcGVfcHJldiAlPiUgc3VtbWFyeSgpCmxtX3Nsb3BlX3ByZXYgJT4lIGNvbmZpbnQobGV2ZWw9MC45KQoKIyBwcmVkaWN0IHNsb3BlcyBmcm9tIHBlcnNvbmFsaXR5IHdpdGggY29udHJvbHMKbG1fc2xvcGVfcHJldl9jdHJsIDwtIGxtKHNsb3BlX3ByZXYgfiAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydF9kaXN0ICsgbWFsZXMgKyBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG91cmlzbSArIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19zbG9wZV9wcmV2KQpsbV9zbG9wZV9wcmV2X2N0cmwgJT4lIHN1bW1hcnkoKQpsbV9zbG9wZV9wcmV2X2N0cmwgJT4lIGNvbmZpbnQobGV2ZWw9MC45KQoKYGBgCgojIyMgQ1JGIHByZWRpY3Rpbmcgc2xvcGVzCmBgYHtyfQoKY3RybHMgPC0gY2ZvcmVzdF91bmJpYXNlZChudHJlZT01MDAsIG10cnk9NSkKCmNyZl9zbG9wZV9wcmV2IDwtIGNmb3Jlc3Qoc2xvcGVfcHJldiB+ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcnNfbyArIHBlcnNfYyArIHBlcnNfZSArIHBlcnNfYSArIHBlcnNfbiArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhaXJwb3J0X2Rpc3QgKyBtYWxlcyArIHBvcGRlbnMgKyBtYW51ZmFjdHVyaW5nICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3VyaXNtICsgaGVhbHRoICsgYWNhZGVtaWMgKyBtZWRpbmMgKyBtZWRhZ2UgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc2VydmF0aXZlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfc2xvcGVfcHJldiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9scyA9IGN0cmxzKQoKY3JmX3Nsb3BlX3ByZXZfdmFyaW1wIDwtIHZhcmltcChjcmZfc2xvcGVfcHJldiwgbnBlcm0gPSAxKQpjcmZfc2xvcGVfcHJldl92YXJpbXBfY29uZCA8LSB2YXJpbXAoY3JmX3Nsb3BlX3ByZXYsIGNvbmRpdGlvbmFsID0gVCwgbnBlcm0gPSAxKQoKY3JmX3Nsb3BlX3ByZXZfdmFyaW1wCmNyZl9zbG9wZV9wcmV2X3ZhcmltcCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpjcmZfc2xvcGVfcHJldl92YXJpbXBfY29uZApjcmZfc2xvcGVfcHJldl92YXJpbXBfY29uZCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmBgYAoKIyMgUHJlZGljdCBTb2NpYWwgRGlzdGFuY2luZwojIyMgQ2hhbmdlIHBvaW50IGFuYWx5c2lzCmBgYHtyfQoKIyBrZWVwIG9ubHkgY291bnRpZXMgd2l0aCBmdWxsIGRhdGEKbnV0c19jb21wbGV0ZSA8LSBkZl91a19zb2NkaXN0X3NjYWxlZCAlPiUgCiAgZ3JvdXBfYnkobnV0czMpICU+JSAKICBzdW1tYXJpemUobiA9IG4oKSkgJT4lIAogIGZpbHRlcihuPT1tYXgoLiRuKSkgJT4lIAogIC4kbnV0czMKCiMgcnVuIGNoYW5nZXBvaW50IGFuYWx5c2lzCmRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgPC0gZGZfdWtfc29jZGlzdF9zY2FsZWQgJT4lIAogIHNlbGVjdChudXRzMywgc29jZGlzdF9zaW5nbGVfdGlsZSkgJT4lCiAgZmlsdGVyKG51dHMzICVpbiUgbnV0c19jb21wbGV0ZSkgJT4lIAogIHNwbGl0KC4kbnV0czMpICU+JQogIG1hcCh+IGNwdC5tZWFudmFyKGFzLnZlY3RvciguJHNvY2Rpc3Rfc2luZ2xlX3RpbGUpLAogICAgICAgICAgICAgICAgICAgICNwZW5hbHR5ID0gJ0FzeW1wdG90aWMnLAogICAgICAgICAgICAgICAgICAgIGNsYXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgcGFyYW0uZXN0aW1hdGVzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgUT0xLAogICAgICAgICAgICAgICAgICAgIHRlc3Quc3RhdCA9ICdOb3JtYWwnKSkKCiMgY2FsY3VsYXRlIGNoYW5nZSBwb2ludApkZl91a19zb2NkaXN0X2NwdF9kYXkgPC0gZGZfdWtfc29jZGlzdF9jcHRfcmVzdWx0cyAlPiUgCiAgbWFwKGNwdHMpICU+JSAKICB1bmxpc3QoKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByZW5hbWUoY3B0X2RheV9zb2NkaXN0ID0gJy4nKSAlPiUKICByb3duYW1lc190b19jb2x1bW4oJ251dHMzJykKCiMgY2FsY3VsYXRlIG1lYW4gZGlmZmVyZW5jZXMKZGZfdWtfc29jZGlzdF9jcHRfbWVhbl9kaWZmIDwtIGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMgJT4lIAogIG1hcChwYXJhbS5lc3QpICU+JSAKICBtYXAofiAuJG1lYW4pICU+JSAKICBtYXAofiAuWzJdLS5bMV0pICU+JSAKICB1bmxpc3QoKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByZW5hbWUobWVhbl9kaWZmX3NvY2Rpc3QgPSAnLicpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbignbnV0czMnKQoKIyBjYWxjdWxhdGUgdmFyYWluY2UgZGlmZmVyZW5jZXMKZGZfdWtfc29jZGlzdF9jcHRfdmFyX2RpZmYgPC0gZGZfdWtfc29jZGlzdF9jcHRfcmVzdWx0cyAlPiUgCiAgbWFwKHBhcmFtLmVzdCkgJT4lIAogIG1hcCh+IC4kdmFyaWFuY2UpICU+JSAKICBtYXAofiAuWzJdLS5bMV0pICU+JSAKICB1bmxpc3QoKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByZW5hbWUodmFyX2RpZmZfc29jZGlzdCA9ICcuJykgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCdudXRzMycpCgojIG1lcmdlIHdpdGggY291bnR5IGRhdGEKZGZfdWtfY3B0X3NvY2Rpc3QgPC0gZGZfdWtfc29jZGlzdF9zY2FsZWQgJT4lIAogIHNlbGVjdCgtdGltZSwgLXJhdGVfZGF5LCAtc29jZGlzdF9zaW5nbGVfdGlsZSkgJT4lCiAgZGlzdGluY3QoKSAlPiUgCiAgbGVmdF9qb2luKGRmX3VrX3NvY2Rpc3RfY3B0X2RheSwgYnk9J251dHMzJykgJT4lCiAgbGVmdF9qb2luKGRmX3VrX3NvY2Rpc3RfY3B0X21lYW5fZGlmZiwgYnk9J251dHMzJykgJT4lCiAgbGVmdF9qb2luKGRmX3VrX3NvY2Rpc3RfY3B0X3Zhcl9kaWZmLCBieT0nbnV0czMnKSAlPiUKICBsZWZ0X2pvaW4obnV0c191dF9rZXksIGJ5PSdudXRzMycpICU+JSAKICBsZWZ0X2pvaW4oc2VsZWN0KGRmX3VrX29uc2V0X3ByZXYsIHV0X2FyZWEsIG9uc2V0X3ByZXYpLCBieT0ndXRfYXJlYScpICU+JQogIGxlZnRfam9pbihzZWxlY3QoZGZfdWtfc2xvcGVfcHJldiwgdXRfYXJlYSwgc2xvcGVfcHJldiksIGJ5PSd1dF9hcmVhJykgJT4lCiAgc2VsZWN0KC11dF9hcmVhKQoKIyBzdGFuZGFyZGl6ZSBtZWFuL3ZhciBkaWZmZXJlbmNlcwpkZl91a19jcHRfc29jZGlzdCA8LSBkZl91a19jcHRfc29jZGlzdCAlPiUgCiAgbXV0YXRlKG1lYW5fZGlmZl9zb2NkaXN0ID0gc2NhbGUobWVhbl9kaWZmX3NvY2Rpc3QpLAogICAgICAgICB2YXJfZGlmZl9zb2NkaXN0ID0gc2NhbGUodmFyX2RpZmZfc29jZGlzdCkpCgojIGhhbmRsZSBjZW5zb3JlZCBkYXRhCmRmX3VrX2NwdF9zb2NkaXN0IDwtIGRmX3VrX2NwdF9zb2NkaXN0ICU+JSAKICBtdXRhdGUoY3B0X2RheV9zb2NkaXN0ID0gaWZlbHNlKGlzLm5hKGNwdF9kYXlfc29jZGlzdCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhkaWZmKHJhbmdlKGRmX3VzJGRhdGUpKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3B0X2RheV9zb2NkaXN0KSkgJT4lIAogIG11dGF0ZShldmVudCA9IGlmZWxzZShjcHRfZGF5X3NvY2Rpc3QgPj0gNjAsIDAsIDEpKQoKYGBgCgpgYGB7cn0KZGZfdWtfY3B0X3NvY2Rpc3QkY3B0X2RheV9zb2NkaXN0ICU+JSBoaXN0KCkKZGZfdWtfY3B0X3NvY2Rpc3QkbWVhbl9kaWZmX3NvY2Rpc3QgJT4lIGhpc3QoKQpkZl91a19jcHRfc29jZGlzdCR2YXJfZGlmZl9zb2NkaXN0ICU+JSBoaXN0KCkKCmBgYAoKYGBge3J9Cgpmb3IoaSBpbiBoZWFkKGRmX3VrX3NvY2Rpc3RfY3B0X3Jlc3VsdHMsIDUpKXsKICBwbG90KGkpCn0KCmBgYAoKCiMgUHJlZGljdGluZyBjaGFuZ2UgcG9pbnRzIHdpdGggdGltZS10by1ldmVudCByZWdyZXNzaW9uIApgYGB7cn0KCiMgcHJlZGljdCBoYXphcmQgZnJvbSBwZXJzb25hbGl0eQpjb3hfY3B0X3NvY2Rpc3QgPC0gY294cGgoU3VydihjcHRfZGF5X3NvY2Rpc3QsIGV2ZW50KSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24sIAogICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3NvY2Rpc3QpCmNveF9jcHRfc29jZGlzdCAlPiUgc3VtbWFyeSgpCgojIHByZWRpY3QgaGF6YXJkIGZyb20gcGVyc29uYWxpdHkgd2l0aCBjb250cm9scwpjb3hfY3B0X3NvY2Rpc3RfY3RybCA8LSBjb3hwaChTdXJ2KGNwdF9kYXlfc29jZGlzdCwgZXZlbnQpIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUsCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfc29jZGlzdCkKY294X2NwdF9zb2NkaXN0X2N0cmwgJT4lIHN1bW1hcnkoKQoKIyBwcmVkaWN0IGhhemFyZCBmcm9tIHBlcnNvbmFsaXR5IHdpdGggY29udHJvbHMKY294X2NwdF9zb2NkaXN0X2N0cmwyIDwtIGNveHBoKFN1cnYoY3B0X2RheV9zb2NkaXN0LCBldmVudCkgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUgKyBvbnNldF9wcmV2ICsgc2xvcGVfcHJldiwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9zb2NkaXN0KQpjb3hfY3B0X3NvY2Rpc3RfY3RybDIgJT4lIHN1bW1hcnkoKQoKYGBgCgojIyMgTGluZWFyIG1vZGVscyBwcmVkaWN0aW5nIG1lYW4gZGlmZmVyZW5jZXMKYGBge3J9CgpsbV9tZWFuZGlmZl9zb2NkaXN0IDwtIGxtKG1lYW5fZGlmZl9zb2NkaXN0IH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24sIAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9zb2NkaXN0KQpsbV9tZWFuZGlmZl9zb2NkaXN0ICU+JSBzdW1tYXJ5KCkKbG1fbWVhbmRpZmZfc29jZGlzdCAlPiUgY29uZmludChsZXZlbD0wLjkpCgpsbV9tZWFuZGlmZl9zb2NkaXN0X2N0cmwgPC0gbG0obWVhbl9kaWZmX3NvY2Rpc3QgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGZfdWtfY3B0X3NvY2Rpc3QpCmxtX21lYW5kaWZmX3NvY2Rpc3RfY3RybCAlPiUgc3VtbWFyeSgpCmxtX21lYW5kaWZmX3NvY2Rpc3RfY3RybCAlPiUgY29uZmludChsZXZlbD0wLjkpCgpsbV9tZWFuZGlmZl9zb2NkaXN0X2N0cmwyIDwtIGxtKG1lYW5fZGlmZl9zb2NkaXN0IH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJzX28gKyBwZXJzX2MgKyBwZXJzX2UgKyBwZXJzX2EgKyBwZXJzX24gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWlycG9ydF9kaXN0ICsgbWFsZXMgKyBwb3BkZW5zICsgbWFudWZhY3R1cmluZyArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG91cmlzbSArIGhlYWx0aCArIGFjYWRlbWljICsgbWVkaW5jICsgbWVkYWdlICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZSArIG9uc2V0X3ByZXYgKyBzbG9wZV9wcmV2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX3VrX2NwdF9zb2NkaXN0KQpsbV9tZWFuZGlmZl9zb2NkaXN0X2N0cmwyICU+JSBzdW1tYXJ5KCkKbG1fbWVhbmRpZmZfc29jZGlzdF9jdHJsMiAlPiUgY29uZmludChsZXZlbD0wLjkpCgpgYGAKCiMjIyBDUkYgcHJlZGljdGluZyBtZWFuIGRpZmZlcmVuY2UKYGBge3J9CgpjdHJscyA8LSBjZm9yZXN0X3VuYmlhc2VkKG50cmVlPTUwMCwgbXRyeT01KQoKY3JmX21lYW5kaWZmX3NvY2Rpc3QgPC0gY2ZvcmVzdChtZWFuX2RpZmZfc29jZGlzdCB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyc19vICsgcGVyc19jICsgcGVyc19lICsgcGVyc19hICsgcGVyc19uICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFpcnBvcnRfZGlzdCArIG1hbGVzICsgcG9wZGVucyArIG1hbnVmYWN0dXJpbmcgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdXJpc20gKyBoZWFsdGggKyBhY2FkZW1pYyArIG1lZGluYyArIG1lZGFnZSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zZXJ2YXRpdmUgKyBvbnNldF9wcmV2ICsgc2xvcGVfcHJldiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl91a19jcHRfc29jZGlzdCAlPiUgZHJvcF9uYSgpLAogICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbHMgPSBjdHJscykKCmNyZl9tZWFuZGlmZl9zb2NkaXN0X3ZhcmltcCA8LSB2YXJpbXAoY3JmX21lYW5kaWZmX3NvY2Rpc3QsIG5wZXJtID0gMSkKY3JmX21lYW5kaWZmX3NvY2Rpc3RfdmFyaW1wX2NvbmQgPC0gdmFyaW1wKGNyZl9tZWFuZGlmZl9zb2NkaXN0LCBjb25kaXRpb25hbCA9IFQsIG5wZXJtID0gMSkKCmNyZl9tZWFuZGlmZl9zb2NkaXN0X3ZhcmltcApjcmZfbWVhbmRpZmZfc29jZGlzdF92YXJpbXAgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKCd2YXJpYWJsZScpICU+JQogIGdncGxvdChhZXMoeD12YXJpYWJsZSwgeT0uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgpjcmZfbWVhbmRpZmZfc29jZGlzdF92YXJpbXBfY29uZApjcmZfbWVhbmRpZmZfc29jZGlzdF92YXJpbXBfY29uZCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSAKICByb3duYW1lc190b19jb2x1bW4oJ3ZhcmlhYmxlJykgJT4lCiAgZ2dwbG90KGFlcyh4PXZhcmlhYmxlLCB5PS4pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCmBgYAoKCiMjIyBFeHBvcnQgZGF0YSAKYGBge3J9CnVrX2xpc3RfcmVzdWx0cyA8LSBsaXN0KGNveF9vbnNldF9wcmV2LCBjb3hfb25zZXRfcHJldl9jdHJsLCAKICAgICBsbV9zbG9wZV9wcmV2LCBsbV9zbG9wZV9wcmV2X2N0cmwsIAogICAgIGNveF9jcHRfc29jZGlzdCwgY294X2NwdF9zb2NkaXN0X2N0cmwsIGNveF9jcHRfc29jZGlzdF9jdHJsMiwKICAgICBsbV9tZWFuZGlmZl9zb2NkaXN0LCBsbV9tZWFuZGlmZl9zb2NkaXN0X2N0cmwsIGxtX21lYW5kaWZmX3NvY2Rpc3RfY3RybDIpCgpyZXN1bHRzX25hbWVzIDwtIGxpc3QoJ2NveF9vbnNldF9wcmV2JywgJ2NveF9vbnNldF9wcmV2X2N0cmwnLCAKICAgICAnbG1fc2xvcGVfcHJldicsICdsbV9zbG9wZV9wcmV2X2N0cmwnLCAKICAgICAnY294X2NwdF9zb2NkaXN0JywgJ2NveF9jcHRfc29jZGlzdF9jdHJsJywgJ2NveF9jcHRfc29jZGlzdF9jdHJsMicsCiAgICAgJ2xtX21lYW5kaWZmX3NvY2Rpc3QnLCAnbG1fbWVhbmRpZmZfc29jZGlzdF9jdHJsJywgJ2xtX21lYW5kaWZmX3NvY2Rpc3RfY3RybDInKQoKbmFtZXModWtfbGlzdF9yZXN1bHRzKSA8LSByZXN1bHRzX25hbWVzCgpzYXZlKHVrX2xpc3RfcmVzdWx0cywgZmlsZT0idWtfbGlzdF9yZXN1bHRzLlJEYXRhIikKCmBgYAoKYGBge3J9CndyaXRlX2NzdihkZl91a19zbG9wZV9wcmV2LCAnZGZfdWtfc2xvcGVfcHJldi5jc3YnKQp3cml0ZV9jc3YoZGZfdWtfY3B0X3NvY2Rpc3QsICdkZl91a19jcHRfc29jZGlzdC5jc3YnKQoKYGBg
Social distancing